package com.cz.video.common.storage.hander;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.cz.video.common.storage.AliyunOssFileStorage;
import com.cz.video.common.storage.constants.AliyunConstants;
import com.cz.video.common.storage.dto.Policy;
import com.cz.video.common.storage.dto.Statement;
import com.cz.video.common.storage.dto.StsSecurityTokenEntity;
import com.cz.video.common.utils.JsonUtils;
import com.cz.video.common.utils.ServletUtils;
import lombok.Data;
import lombok.SneakyThrows;

import java.util.HashMap;
import java.util.List;

/**
 * @ClassName : AliyunStsHandler
 * @Description : 阿里云申请sts凭证处理器
 * @Author : 陈智
 * @Date: 2023/7/8  14:42
 */
@Data
public class AliyunStsHandler {

  /**
   * 角色Arn
   */
  private String arn="";

  /**
   * 申请STS所用的endpoint
   */
  private String stsEndpoint="";

  /**
   * 申请STS所用的访问key
   */
  private String stsAccessKey;

  /**
   * 申请STS所用的访问密钥
   */
  private String stsAccessSecret;


  /**
   * sts持续时间
   */
  private long stsDuration;

  /**
   * 区域ID,sts服务器和oss服务器的区域id是统一的
   */
  private String regionId = "";


  /**
   * 用于申请sts的客户端实例
   */
  private  volatile IAcsClient acsClient;

  /**
   * 获取acsClient单例
   * 使用了双重检查锁定来确保线程安全
   * @return AcsClient
   */
  public IAcsClient getAcsClient() {
    if (acsClient == null) {
      synchronized (AliyunOssFileStorage.class) {
        if (acsClient == null) {
          // 添加endpoint
          DefaultProfile.addEndpoint(regionId, "Sts", stsEndpoint);
          IClientProfile profile = DefaultProfile.getProfile(regionId, stsAccessKey, stsAccessSecret);
          acsClient = new DefaultAcsClient(profile);
        }
      }
    }
    return acsClient;
  }



  /**
   * 根据策略，请求得到sst凭证
   * @param policy 策略内容
   * @return sst凭证
   */

  public StsSecurityTokenEntity getStsSecurityTokenEntity(String policy) {
    StsSecurityTokenEntity certificate = new StsSecurityTokenEntity();
    try {
      String roleSessionName = "stsUploadRoleSession";//自定义
      IAcsClient acsClient = getAcsClient();
      final AssumeRoleRequest request = new AssumeRoleRequest();
      request.setSysMethod(MethodType.POST);
      request.setRoleArn(arn);
      request.setRoleSessionName(roleSessionName);
      request.setPolicy(policy);
      request.setDurationSeconds(stsDuration);

      final AssumeRoleResponse response = acsClient.getAcsResponse(request);
      certificate.setAccessKeyId(response.getCredentials().getAccessKeyId())
        .setAccessKeySecret(response.getCredentials().getAccessKeySecret())
        .setExpiration(response.getCredentials().getExpiration())
        .setSecurityToken(response.getCredentials().getSecurityToken())
      ;
    } catch (ClientException e) {
      e.printStackTrace();
    }
    return certificate;
  }


  /**
   * 构建策略
   * @return 策略的json
   */

  @SneakyThrows
  public String buildPolicy(List<Statement> statements){
    Policy policy = new Policy();

    //限制只有源ip才能使用凭证
    statements.forEach(statement -> {
      HashMap<String, String> ipCondition = new HashMap<>();
      ipCondition.put(AliyunConstants.SOURCE_IP, ServletUtils.getClientIP());
      statement.addCondition(AliyunConstants.IP_ADDRESS,ipCondition);
    });
    //版本号默认为1
    policy.setVersion("1");
    policy.setStatement(statements);
    // 将 policy 对象序列化为 JSON
    return JsonUtils.toJsonString(policy);
  }

  /**
   * 关闭 client
   */
  public void close() {
    if (acsClient != null) {
      acsClient.shutdown();
      acsClient = null;
    }
  }
}
